package org.jef.core.mask;

import cn.hutool.core.util.ObjectUtil;
import jef.tools.CacheMap;
import org.apache.commons.lang3.StringUtils;

import jef.tools.bean.BeanUtils;
import org.jef.core.exception.BaseException;

import javax.management.ReflectionException;
import java.lang.reflect.Field;
import java.util.*;

/**
 * 值定制计算工具类
 *
 * @Company Asiainfo-Linkage Technologies (China), Inc.
 * @author luolp@asiainfo-linkage.com
 * @Date 2012-9-13
 */
public final class EvalUtil {

    private static final String CONNECTOR_FOR_OBJ_FIELD = ".";

    /**
     * class中所有带有get、set方法的fields缓存<br>
     * {@code key} = class完整名称
     */
    private static final CacheMap<String, Collection<Field>> allFieldsCache =
            new CacheMap<String, Collection<Field>>(100);

    /**
     * class中所有带有get、set方法的fields名称缓存<br>
     * {@code key} = class完整名称
     */
    private static final CacheMap<String, Field> allFieldsNameCache =
            new CacheMap<String, Field>(100);

    /**
     * class中所有带有get、set方法和Eval注解的fields缓存<br>
     * {@code key} = class完整名称<b>.</b>field名称
     */
    private static final CacheMap<String, Collection<Field>> evalFieldsCache =
            new CacheMap<String, Collection<Field>>(200);

    /**
     * class中所有带有get、set方法和Eval注解的fields上的Eval注解缓存<br>
     * {@code key} = class完整名称<b>.</b>field名称
     */
    private static final CacheMap<String, Eval> evalCache =
            new CacheMap<String, Eval>(200);

    /**
     * 确定策略类（以strategyClassName指定的类为优先）
     *
     * @param evalAnno
     * @return
     * @throws ReflectionException
     */
    private static EvalStrategy determineStrategyClass(Eval evalAnno) throws ReflectionException {
        EvalStrategy evalStrategy = null;
        if (StringUtils.isNotBlank(evalAnno.strategyClassName())) { // 以strategyClassName为优先
            evalStrategy = (EvalStrategy) BeanUtils.newInstance(
                    evalAnno.strategyClassName(), (Object[]) evalAnno.constructParams());
        } else {
            evalStrategy = BeanUtils.newInstance(evalAnno.strategyClass(),
                    (Object[]) evalAnno.constructParams());
        }
        return evalStrategy;
    }



    public static String getEvalValue(Eval evalAnno, Object instance, Object rawFieldValue) {
        String wrappedValue;
        try {
            EvalStrategy strategy = determineStrategyClass(evalAnno);
            if (strategy == null) {
                throw new IllegalArgumentException(concat("Create instance fail: ",
                        evalAnno.strategyClassName() != null ? evalAnno.strategyClassName() :
                                evalAnno.strategyClass().toString(),
                        " constructParams: ", Arrays.toString(evalAnno.constructParams())));
            }
            wrappedValue = strategy.eval(rawFieldValue, instance);
        } catch (ReflectionException e) {
            throw new BaseException(e);
        }
        return wrappedValue;
    }

    private static String getKeyForField(String keyForObj, String fieldName) {
        return concat(keyForObj, CONNECTOR_FOR_OBJ_FIELD, fieldName);
    }

    /**
     * 合并多个String,在参数为3个和以内时请直接使用String.concat。
     * 5个和超过5个String相加后，concat方法性能急剧下降，此时此方法最快
     *
     * @param args
     * @return
     */
    public final static String concat(String... args) {
        if (args.length == 1)
            return args[0];
        int n = 0;
        for (String s : args) {
            if (s == null)
                continue;
            n += s.length();
        }
        StringBuilder sb = new StringBuilder(n);
        for (String s : args) {
            if (s == null)
                continue;
            sb.append(s);
        }
        return sb.toString();
    }
}
